# hashlib 安全哈希与消息摘要
import hashlib

str = b'Nobody inspects the spammish repetition'
# 获取所有支持的哈希算法的名称集合
print(
    hashlib.algorithms_guaranteed)  # {'blake2b', 'sha3_256', 'sha3_224', 'shake_256', 'sha1', 'sha384', 'sha512', 'sha3_384', 'sha3_512', 'md5', 'shake_128', 'blake2s', 'sha256', 'sha224'}

# 获取在所运行的python解释器上可用的哈希算法的名称集合
print(
    hashlib.algorithms_available)  # {'sha224', 'SHA512', 'ripemd160', 'md4', 'dsaWithSHA', 'SHA224', 'shake_128', 'sha384', 'sha', 'MD4', 'whirlpool', 'SHA384', 'blake2s', 'shake_256', 'sha512', 'SHA1', 'SHA', 'sha3_224', 'DSA', 'sha1', 'SHA256', 'dsaEncryption', 'DSA-SHA', 'sha3_384', 'sha3_512', 'md5', 'MD5', 'RIPEMD160', 'ecdsa-with-SHA1', 'sha3_256', 'blake2b', 'sha256'}

# 获取字符串的摘要 - 简略写法
hash_str = hashlib.sha256(str).hexdigest()
print(hash_str)  # 031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406
print(hashlib.md5(str).hexdigest())  # bb649c83dd1ea5c9d9dec9a18df0ffe9

# 哈希器对象
m = hashlib.sha256()
# m = hashlib.new('sha256')

# 用 bytes-like object 来更新哈希对象
m.update(str)

# 返回当前已传给 update() 方法的数据摘要
print(m.digest())  # b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'

# 类似于 digest() 但摘要会以两倍长度字符串对象的形式返回，其中仅包含十六进制数码
print(m.hexdigest())  # 031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406

# 此哈希对象的规范名称-
print(m.name)  # sha256

# 字节表示结果哈希对象的大小
print(m.digest_size)  # 32

# 字节表示的哈希算法的内部快大小
print(m.block_size)  # 64

# 克隆哈希对象
print(m.copy())  # <sha256 HASH object @ 0x00000144E904EA08>

# shake_128 与 shake_256 算法支持可变长度
n = hashlib.shake_128()
n.update(str)
# 长度为16
print(n.digest(16))

# 长度为32
print(n.hexdigest(16))  # 4194c310e4afc9ff96a747d0c02a7db8

# 密钥派生 加盐算法 用于安全密码哈希
# 函数提供 PKCS#5 基于密码的密钥派生函数 使用 HMAC 作为伪随机函数
dk = hashlib.pbkdf2_hmac('sha256', b'password-user', b'salt', 1000)
print(dk.hex())  # 502145b69faffc005e32385f8efd7059e845732ea61976a5d1559613f8150cb9

# hmac 模块实现了 HMAC 算法
import hmac

str = b'I will love you forever'

# 创建hmac加密器对象  secret 是一个指定密钥的 bytes 或 bytearray 对象
o = hmac.new(b'secret')

# 更新 hmac 对象
o.update(str)

# 返回当前已传给 update() 方法的字节串数据的摘要
print(o.digest())  # b'A\x94\x12$\x15\x1a\xe3\x82\xfb\x0b@\xc2\x91\x87\x7f\xe4'

# 类似于 digest() 但摘要会以两倍长度字符串的形式返回，其中仅包含十六进制数码
print(o.hexdigest())  # 41941224151ae382fb0b40c291877fe4

# 此哈希对象的规范名称-
print(o.name)  # hmac-md5

# 字节表示结果哈希对象的大小
print(o.digest_size)  # 16

# 字节表示的哈希算法的内部快大小
print(o.block_size)  # 64

# 克隆哈希对象
print(o.copy())  # <hmac.HMAC object at 0x00000215F325C390>

# secrets 管理密码的安全随机数
import secrets

# 从序列中随机选取元素
print(secrets.choice(['a', 'b', 'c']), secrets.choice('abd'))

# 从[0,n)随机取随机整数
print(secrets.randbelow(10))

# 返回5个随机比特位的整数
print(secrets.randbits(5))

# 返回 16bytes 个字节的随机字节字符串
print(secrets.token_bytes(16))

# 返回十六进制随机文本字符串
print(secrets.token_hex(16))

# 返回安全的 URL 随机文本字符串
print(secrets.token_urlsafe(16))

